import requests
import socket
from datetime import datetime, timezone, timedelta
import subprocess
import os
import tkinter as tk
from tkinter import ttk, messagebox
import json
import schedule
import time
import threading
import logging
import re
import winreg
import sys
from PIL import Image, ImageTk, ImageDraw, ImageFont
import pystray
import keyboard

CONFIG_FILE = 'update_config.json'

def setup_logger():
    log_dir = 'logs'
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)
    
    log_file = os.path.join(log_dir, 'ip_update.log')
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s [%(levelname)s] %(message)s',
        handlers=[
            logging.FileHandler(log_file, encoding='utf-8'),
            logging.StreamHandler()
        ]
    )
    return logging.getLogger(__name__)

class UpdateSchedulerGUI:
    def __init__(self, root):
        self.logger = setup_logger()
        self.root = root
        self.root.title("IP信息更新调度器")
        self.root.geometry("500x300")
        
        # 创建线程安全的变量
        self._update_hour = "00"
        self._update_minute = "00"
        self._scheduler_running = True
        self._schedule_lock = threading.Lock()
        self._exit_event = threading.Event()
        self.scheduler_thread = None
        
        # 记录程序启动
        self.logger.info("="*50)
        self.logger.info("IP信息更新程序启动")
        
        # 添加监控间隔的变量
        self._monitor_interval = tk.StringVar(value="5")  # 默认5分钟
        self._last_ips = {"local": "", "ipv4": "", "ipv6": ""}
        self._monitoring = False
        self._monitor_thread = None
        
        # 1. 首先创建所有GUI元素
        self.create_gui_elements()
        
        # 2. 设置托盘图标
        self.setup_tray()
        
        # 3. 绑定窗口事件
        self.root.protocol('WM_DELETE_WINDOW', self.hide_window)
        self.root.bind("<Unmap>", self.on_minimize)
        
        # 4. 加载设置
        self.load_settings()
        
        # 5. 更新IP显示并检查是否需要提交
        self.update_ip_display()
        self.check_initial_ip_changes()
        
        # 6. 启动调度器
        self.start_scheduler()
        
        # 8. 如果是以最小化方式启动，则隐藏窗口
        if "--minimized" in sys.argv:
            self.root.withdraw()
        
        # 注册全局快捷键
        self.setup_hotkey()
    
    def create_gui_elements(self):
        """创建所有GUI元素"""
        # 创建左右分栏
        left_frame = ttk.Frame(self.root, padding="5")
        left_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=5)
        
        separator = ttk.Separator(self.root, orient='vertical')
        separator.grid(row=0, column=1, sticky=(tk.N, tk.S), padx=5)
        
        right_frame = ttk.Frame(self.root, padding="5")
        right_frame.grid(row=0, column=2, sticky=(tk.W, tk.E, tk.N, tk.S), padx=5)
        
        # 配置列的权重
        self.root.grid_columnconfigure(0, weight=1)
        self.root.grid_columnconfigure(1, weight=0)
        self.root.grid_columnconfigure(2, weight=1)
        
        # 在右侧添加IP信息显示
        self.create_right_frame(right_frame)
        
        # 添加底部分隔线
        ttk.Separator(right_frame, orient='horizontal').pack(fill=tk.X, pady=5)
        
        # IP监控设置
        self.create_left_frame(left_frame)
    
    def create_left_frame(self, left_frame):
        """创建左侧框架的GUI元素"""
        # IP监控设置
        monitor_frame = ttk.LabelFrame(left_frame, text="IP变动监控", padding=5)
        monitor_frame.grid(row=0, column=0, columnspan=2, sticky='ew', pady=5)
        
        ttk.Label(monitor_frame, text="检查间隔:").grid(row=0, column=0, padx=5)
        
        # 修改间隔时间选择下拉框的选项
        self.interval_combo = ttk.Combobox(monitor_frame, width=5, 
                                         textvariable=self._monitor_interval)
        self.interval_combo['values'] = ["3", "5", "10", "15", "30", "60", "120"]
        self.interval_combo.grid(row=0, column=1, padx=5)
        ttk.Label(monitor_frame, text="分钟").grid(row=0, column=2, padx=2)
        
        # 监控开关
        self.monitor_var = tk.BooleanVar(value=False)
        self.monitor_switch = ttk.Checkbutton(monitor_frame, text="启用监控", 
                                            variable=self.monitor_var,
                                            command=self.toggle_monitor)
        self.monitor_switch.grid(row=1, column=0, columnspan=3, pady=5)
        
        # 添加分隔线
        ttk.Separator(left_frame, orient='horizontal').grid(
            row=1, column=0, columnspan=2, sticky='ew', pady=10)
        
        # 定时更新设置（使用相同的LabelFrame样式）
        update_frame = ttk.LabelFrame(left_frame, text="定时更新设置", padding=5)
        update_frame.grid(row=2, column=0, columnspan=2, sticky='ew', pady=5)
        
        # 小时选择
        ttk.Label(update_frame, text="小时:").grid(row=0, column=0, padx=5)
        self.hour_var = tk.StringVar(value="00")
        self.hour_combo = ttk.Combobox(update_frame, textvariable=self.hour_var, width=5)
        self.hour_combo['values'] = [f"{i:02d}" for i in range(24)]
        self.hour_combo.grid(row=0, column=1, padx=5)
        
        # 分钟选择
        ttk.Label(update_frame, text="分钟:").grid(row=1, column=0, padx=5)
        self.minute_var = tk.StringVar(value="00")
        self.minute_combo = ttk.Combobox(update_frame, textvariable=self.minute_var, width=5)
        self.minute_combo['values'] = [f"{i:02d}" for i in range(60)]
        self.minute_combo.grid(row=1, column=1, padx=5)
        
        # 状态显示
        self.status_var = tk.StringVar(value="当前未运行")
        ttk.Label(update_frame, textvariable=self.status_var).grid(
            row=2, column=0, columnspan=2, pady=5)
        
        # 按钮区域
        button_frame = ttk.Frame(left_frame)
        button_frame.grid(row=3, column=0, columnspan=2, pady=10)
        
        ttk.Button(button_frame, text="保存设置", command=self.save_settings).pack(side=tk.LEFT, padx=5)
        self.update_button = ttk.Button(button_frame, text="立即更新", command=self.update_now)
        self.update_button.pack(side=tk.LEFT, padx=5)
    
    def create_right_frame(self, right_frame):
        """创建右侧框架的GUI元素"""
        # 添加自动启动选项到右上角
        autostart_frame = ttk.Frame(right_frame)
        autostart_frame.pack(fill=tk.X, pady=5)
        self.autostart_var = tk.BooleanVar(value=self.check_autostart())
        ttk.Checkbutton(autostart_frame, text="开机自动启动", 
                        variable=self.autostart_var, 
                        command=self.toggle_autostart).pack(side=tk.RIGHT)
        
        # IP信息显示区域
        self.ip_info_frame = ttk.Frame(right_frame)
        self.ip_info_frame.pack(fill=tk.BOTH, expand=True, pady=10)
        
        # 标题和更新时间
        title_frame = ttk.Frame(self.ip_info_frame)
        title_frame.grid(row=0, column=0, columnspan=3, sticky='ew', pady=(0, 5))
        
        # 使用更好看的标题样式
        title_label = ttk.Label(title_frame, text="当前IP信息", font=('Microsoft YaHei UI', 11, 'bold'))
        title_label.pack(side=tk.LEFT)
        
        # 更新时间显示
        self.update_time_var = tk.StringVar(value="")
        time_label = ttk.Label(title_frame, textvariable=self.update_time_var, 
                              font=('Microsoft YaHei UI', 8), foreground='#666666')
        time_label.pack(side=tk.RIGHT)
        
        # 各IP地址显示
        self.local_ip_var = tk.StringVar(value="获取中...")
        self.ipv4_var = tk.StringVar(value="获取中...")
        self.ipv6_var = tk.StringVar(value="获取中...")
        
        # 使用网格布局来对齐标签和值
        style = ttk.Style()
        style.configure('IP.TLabel', font=('Microsoft YaHei UI', 9))
        
        # 本地IP
        ttk.Label(self.ip_info_frame, text="本地IP", style='IP.TLabel').grid(
            row=1, column=0, sticky=tk.E, padx=(5,2), pady=5)
        ttk.Label(self.ip_info_frame, text=":", style='IP.TLabel').grid(
            row=1, column=1, sticky=tk.W, padx=0, pady=5)
        local_ip_entry = tk.Entry(self.ip_info_frame, textvariable=self.local_ip_var, 
                                 font=('Consolas', 9), readonlybackground='white', state='readonly')
        local_ip_entry.grid(row=1, column=2, sticky=tk.W, padx=(2,5), pady=5)
        
        # IPv4
        ttk.Label(self.ip_info_frame, text="公网IPv4", style='IP.TLabel').grid(
            row=2, column=0, sticky=tk.E, padx=(5,2), pady=5)
        ttk.Label(self.ip_info_frame, text=":", style='IP.TLabel').grid(
            row=2, column=1, sticky=tk.W, padx=0, pady=5)
        ipv4_entry = tk.Entry(self.ip_info_frame, textvariable=self.ipv4_var, 
                               font=('Consolas', 9), readonlybackground='white', state='readonly')
        ipv4_entry.grid(row=2, column=2, sticky=tk.W, padx=(2,5), pady=5)
        
        # IPv6
        ttk.Label(self.ip_info_frame, text="公网IPv6", style='IP.TLabel').grid(
            row=3, column=0, sticky=tk.E, padx=(5,2), pady=5)
        ttk.Label(self.ip_info_frame, text=":", style='IP.TLabel').grid(
            row=3, column=1, sticky=tk.W, padx=0, pady=5)
        ipv6_entry = tk.Entry(self.ip_info_frame, textvariable=self.ipv6_var, 
                               font=('Consolas', 9), readonlybackground='white', state='readonly', width=30)
        ipv6_entry.grid(row=3, column=2, sticky=tk.W, padx=(2,5), pady=5)
        
        # 配置网格列的权重
        self.ip_info_frame.grid_columnconfigure(2, weight=1)
    
    def setup_tray(self):
        """设置系统托盘图标"""
        try:
            # 创建图标
            icon_size = 32
            icon_image = Image.new('RGBA', (icon_size, icon_size), color=(0, 0, 0, 0))
            draw = ImageDraw.Draw(icon_image)
            
            # 绘制渐变背景
            for i in range(icon_size):
                color = (33, 150, 243, int(255 * (1 - i/icon_size)))  # 使用Material Design蓝色
                draw.line([(0, i), (icon_size, i)], fill=color)
            
            # 绘制圆形
            padding = 2
            draw.ellipse([padding, padding, icon_size-padding-1, icon_size-padding-1], 
                         outline='#2196F3', width=2)
            
            # 添加文字
            try:
                # 尝试使用微软雅黑
                font = ImageFont.truetype("msyh.ttc", 16)
            except:
                try:
                    font = ImageFont.truetype("arial.ttf", 16)
                except:
                    font = ImageFont.load_default()
            
            # 绘制文字
            text = "IP"
            text_bbox = draw.textbbox((0, 0), text, font=font)
            text_width = text_bbox[2] - text_bbox[0]
            text_height = text_bbox[3] - text_bbox[1]
            x = (icon_size - text_width) // 2
            y = (icon_size - text_height) // 2
            
            # 添加文字阴影效果
            draw.text((x+1, y+1), text, fill='#1976D2', font=font)  # 阴影
            draw.text((x, y), text, fill='#FFFFFF', font=font)  # 主文字
            
            def on_activate(icon):
                self.root.after(0, self.show_window)
            
            menu = (
                pystray.MenuItem("显示主窗口", self.show_window),
                pystray.MenuItem("立即更新", self.update_now),
                pystray.MenuItem("退出程序", self.quit_window)
            )
            
            self.tray_icon = pystray.Icon(
                "IP更新器",
                icon_image,
                "IP更新器",
                menu
            )
            
            # 设置双击事件（通过设置 on_activate）
            self.tray_icon.on_activate = on_activate
            
            # 启动托盘图标
            threading.Thread(target=self.tray_icon.run, daemon=True).start()
            
        except Exception as e:
            self.logger.error(f"设置托盘图标失败: {e}")
            self.tray_icon = None
    
    def hide_window(self):
        """隐藏窗口到系统托盘"""
        try:
            if hasattr(self, 'tray_icon') and self.tray_icon:
                self.root.withdraw()
                self.tray_icon.visible = True
            else:
                self.logger.error("托盘图标未初始化，无法隐藏窗口")
        except Exception as e:
            self.logger.error(f"隐藏窗口失败: {e}")
    
    def show_window(self, icon=None):
        """从系统托盘显示窗口"""
        try:
            # 确保在主线程中执行
            def _show():
                if not self.root.winfo_viewable():  # 检查窗口是否可见
                    self.tray_icon.visible = False
                    self.root.deiconify()
                    self.root.lift()
                    self.root.focus_force()
                
            if threading.current_thread() is threading.main_thread():
                _show()
            else:
                self.root.after(0, _show)
        except Exception as e:
            self.logger.error(f"显示窗口失败: {e}")
    
    def quit_window(self):
        """完全退出程序"""
        try:
            # 停止监控
            self._monitoring = False
            if self._monitor_thread and self._monitor_thread.is_alive():
                self._monitor_thread.join(timeout=1.0)
            
            # 移除快捷键
            try:
                keyboard.remove_hotkey('ctrl+.')
            except:
                pass
            
            # 设置退出标志
            self._exit_event.set()
            
            # 停止托盘图标
            if hasattr(self, 'tray_icon') and self.tray_icon:
                self.tray_icon.visible = False
                self.tray_icon.stop()
            
            # 等待调度器线程结束
            if self.scheduler_thread and self.scheduler_thread.is_alive():
                self.scheduler_thread.join(timeout=1.0)
            
            # 销毁窗口
            self.root.destroy()
        except Exception as e:
            self.logger.error(f"退出程序时发生错误: {e}")
            self.root.destroy()  # 确保窗口被销毁
    
    def check_autostart(self):
        """检查是否已设置自动启动"""
        try:
            key = winreg.OpenKey(
                winreg.HKEY_CURRENT_USER,
                r"Software\Microsoft\Windows\CurrentVersion\Run",
                0,
                winreg.KEY_READ
            )
            try:
                winreg.QueryValueEx(key, "IP更新器")
                return True
            except WindowsError:
                return False
            finally:
                winreg.CloseKey(key)
        except WindowsError:
            return False
    
    def toggle_autostart(self):
        """切换自动启动状态"""
        try:
            key = winreg.OpenKey(
                winreg.HKEY_CURRENT_USER,
                r"Software\Microsoft\Windows\CurrentVersion\Run",
                0,
                winreg.KEY_ALL_ACCESS
            )
            
            if self.autostart_var.get():
                # 获取当前运行的exe完整路径
                exe_path = os.path.abspath(sys.executable)  # 使用 sys.executable 而不是 sys.argv[0]
                # 确保路径使用双引号包裹，并使用完整路径
                cmd = f'"{exe_path}" --minimized'
                
                # 记录日志
                self.logger.info(f"设置自动启动命令: {cmd}")
                
                try:
                    # 先尝试删除已存在的键值（如果有的话）
                    try:
                        winreg.DeleteValue(key, "IP更新器")
                    except WindowsError:
                        pass
                    
                    # 设置新的键值
                    winreg.SetValueEx(
                        key,
                        "IP更新器",
                        0,
                        winreg.REG_SZ,
                        cmd
                    )
                    
                    # 验证设置是否成功
                    value, _ = winreg.QueryValueEx(key, "IP更新器")
                    if value == cmd:
                        self.logger.info("已成功添加开机自动启动")
                        messagebox.showinfo("成功", "已设置开机自动启动")
                    else:
                        raise Exception("注册表验证失败")
                        
                except Exception as e:
                    error_msg = f"设置注册表失败: {e}"
                    self.logger.error(error_msg)
                    raise Exception(error_msg)
            else:
                # 移除自动启动
                try:
                    winreg.DeleteValue(key, "IP更新器")
                    self.logger.info("已移除开机自动启动")
                    messagebox.showinfo("成功", "已移除开机自动启动")
                except WindowsError as e:
                    self.logger.error(f"移除自动启动失败: {e}")
                    pass
            
            winreg.CloseKey(key)
            
            # 额外验证
            self.verify_autostart_setting()
            
        except Exception as e:
            error_msg = f"设置自动启动失败: {e}"
            self.logger.error(error_msg)
            messagebox.showerror("错误", error_msg)
    
    def verify_autostart_setting(self):
        """验证自动启动设置是否正确"""
        try:
            key = winreg.OpenKey(
                winreg.HKEY_CURRENT_USER,
                r"Software\Microsoft\Windows\CurrentVersion\Run",
                0,
                winreg.KEY_READ
            )
            
            try:
                value, _ = winreg.QueryValueEx(key, "IP更新器")
                self.logger.info(f"当前注册表中的启动命令: {value}")
                
                if self.autostart_var.get():
                    exe_path = os.path.abspath(sys.argv[0])
                    expected_cmd = f'"{exe_path}" --minimized'
                    
                    if value != expected_cmd:
                        self.logger.warning(f"注册表中的命令与预期不符")
                        self.logger.warning(f"预期: {expected_cmd}")
                        self.logger.warning(f"实际: {value}")
                
            except WindowsError:
                if self.autostart_var.get():
                    self.logger.warning("未找到自动启动设置")
            
            winreg.CloseKey(key)
            
        except Exception as e:
            self.logger.error(f"验证自动启动设置失败: {e}")
    
    def load_settings(self):
        try:
            if os.path.exists(CONFIG_FILE):
                with open(CONFIG_FILE, 'r') as f:
                    config = json.load(f)
                    with self._schedule_lock:
                        self._update_hour = config.get('hour', '00')
                        self._update_minute = config.get('minute', '00')
                        self.hour_var.set(self._update_hour)
                        self.minute_var.set(self._update_minute)
        except Exception as e:
            messagebox.showerror("错误", f"加载配置失败: {e}")
    
    def save_settings(self):
        try:
            # 使用线程安全的方式更新时间
            with self._schedule_lock:
                self._update_hour = self.hour_var.get()
                self._update_minute = self.minute_var.get()
                
                config = {
                    'hour': self._update_hour,
                    'minute': self._update_minute
                }
                with open(CONFIG_FILE, 'w') as f:
                    json.dump(config, f)
            
            # 重新设置调度
            schedule.clear()
            self.schedule_update()
            self.logger.info(f"更新时间设置已保存: {self._update_hour}:{self._update_minute}")
            messagebox.showinfo("成功", "设置已保存并更新调度")
        except Exception as e:
            error_msg = f"保存配置失败: {e}"
            self.logger.error(error_msg)
            messagebox.showerror("错误", error_msg)
    
    def update_now(self):
        """修改更新方法，添加更多日志记录"""
        try:
            self.update_button.configure(text="更新中...", state='disabled')
            self.status_var.set("正在更新...")
            self.root.update()
            
            # 先更新显示的IP信息
            self.update_ip_display()
            
            # 获取更新前的IP信息
            old_content = ""
            if os.path.exists('README.md'):
                with open('README.md', 'r', encoding='utf-8') as f:
                    old_content = f.read()
            
            # 获取新IP信息并更新文件
            markdown_content = generate_markdown()
            update_markdown_file(markdown_content)
            
            # 记录IP变化
            self.log_ip_changes(old_content, markdown_content)
            
            # Git操作
            commit_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            commit_message = f"Update IP info: {commit_time}"
            
            # 提交当前目录下所有变动
            subprocess.run(['git', 'add', '.'], check=True)
            subprocess.run(['git', 'commit', '-m', commit_message], check=True)
            subprocess.run(['git', 'push'], check=True)
            
            self.logger.info(f"所有变动已更新并提交 - {commit_time}")
            self.status_var.set("更新完成")
            
        except Exception as e:
            self.logger.error(f"更新失败: {e}")
            self.status_var.set("更新失败")
            messagebox.showerror("错误", f"更新失败: {e}")
        finally:
            # 恢复按钮状态
            self.update_button.configure(text="立即更新", state='normal')
    
    def schedule_update(self):
        """修改调度器更新方法，避免线程问题"""
        try:
            with self._schedule_lock:
                update_time = f"{self._update_hour}:{self._update_minute}"
                schedule.every().day.at(update_time).do(self.update_now)
                # 使用队列更新状态
                status_message = f"已设置每天 {update_time} 更新"
                if not self._exit_event.is_set():
                    self.root.after(0, lambda m=status_message: self.status_var.set(m))
        except Exception as e:
            self.logger.error(f"设置调度更新失败: {e}")
    
    def run_scheduler(self):
        """调度器运行方法"""
        try:
            self.schedule_update()
            while not self._exit_event.is_set():
                schedule.run_pending()
                time.sleep(1)
        except Exception as e:
            self.logger.error(f"调度器运行错误: {e}")
    
    def log_ip_changes(self, old_content, new_content):
        try:
            def extract_ips(content):
                local = re.search(r'本地IP地址 \| `(.*?)`', content)
                ipv4 = re.search(r'公网IPv4地址 \| `(.*?)`', content)
                ipv6 = re.search(r'公网IPv6地址 \| `(.*?)`', content)
                return {
                    '本地IP': local.group(1) if local else "无",
                    'IPv4': ipv4.group(1) if ipv4 else "无",
                    'IPv6': ipv6.group(1) if ipv6 else "无"
                }
            
            new_ips = extract_ips(new_content)
            
            if not old_content:
                self.logger.info(f"当前IP - IPv4: {new_ips['IPv4']}, IPv6: {new_ips['IPv6']}")
                return
            
            old_ips = extract_ips(old_content)
            
            # 记录当前IP
            self.logger.info(f"当前IP - IPv4: {new_ips['IPv4']}, IPv6: {new_ips['IPv6']}")
            
            # 检查变动
            if old_ips['IPv4'] != new_ips['IPv4']:
                self.logger.info(f"IPv4变更: {old_ips['IPv4']} -> {new_ips['IPv4']}")
            
            if old_ips['IPv6'] != new_ips['IPv6']:
                self.logger.info(f"IPv6变更: {old_ips['IPv6']} -> {new_ips['IPv6']}")
            
            if old_ips['IPv4'] == new_ips['IPv4'] and old_ips['IPv6'] == new_ips['IPv6']:
                self.logger.info("IP地址未发生变化")
            
        except Exception as e:
            self.logger.error(f"记录IP变化失败: {e}")
    
    def on_minimize(self, event):
        """处理最小化事件"""
        try:
            # 检查是否是真正的最小化事件（而不是其他原因的Unmap）
            if self.root.state() == 'iconic':
                # 取消最小化状态并隐藏到托盘
                self.hide_window()
        except Exception as e:
            self.logger.error(f"最小化处理失败: {e}")
    
    def update_ip_display(self):
        """更新IP信息显示"""
        try:
            local_ip = get_local_ip()
            ipv4 = get_ipv4()
            ipv6 = get_ipv6()
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            
            # 使用事件队列更新界面
            self.root.after(0, lambda: [
                self.local_ip_var.set(local_ip),
                self.ipv4_var.set(ipv4),
                self.ipv6_var.set(ipv6),
                self.update_time_var.set(current_time)
            ])
        except Exception as e:
            self.logger.error(f"更新IP显示失败: {e}")
    
    def update_now_from_tray(self):
        """从托盘菜单调用更新时的处理方法"""
        # 先显示主窗口
        self.show_window()
        # 然后执行更新
        self.update_now()
    
    def start_scheduler(self):
        """安全地启动调度器"""
        if self.scheduler_thread is None or not self.scheduler_thread.is_alive():
            self.scheduler_thread = threading.Thread(target=self.run_scheduler, daemon=True)
            self.scheduler_thread.start()
    
    def setup_hotkey(self):
        """设置全局快捷键"""
        try:
            # 注册 Ctrl+. 快捷键
            keyboard.add_hotkey('ctrl+.', self.show_window_hotkey)
            self.logger.info("全局快捷键已注册: Ctrl+.")
        except Exception as e:
            self.logger.error(f"注册全局快捷键失败: {e}")
    
    def show_window_hotkey(self):
        """快捷键显示窗口的处理方法"""
        try:
            # 确保在主线程中执行
            self.root.after(0, self.show_window)
        except Exception as e:
            self.logger.error(f"快捷键显示窗口失败: {e}")
    
    def toggle_monitor(self):
        """切换监控状态"""
        if self.monitor_var.get():
            self.start_monitor()
        else:
            self.stop_monitor()
    
    def start_monitor(self):
        """启动IP监控"""
        try:
            self._monitoring = True
            self._last_ips = {
                "local": self.local_ip_var.get(),
                "ipv4": self.ipv4_var.get(),
                "ipv6": self.ipv6_var.get()
            }
            
            if not self._monitor_thread or not self._monitor_thread.is_alive():
                self._monitor_thread = threading.Thread(target=self.monitor_ip_changes, 
                                                     daemon=True)
                self._monitor_thread.start()
            
            self.interval_combo.configure(state='disabled')
            self.logger.info(f"IP监控已启动，间隔: {self._monitor_interval.get()}分钟")
        except Exception as e:
            self.logger.error(f"启动监控失败: {e}")
            self.monitor_var.set(False)
    
    def stop_monitor(self):
        """停止IP监控"""
        self._monitoring = False
        self.interval_combo.configure(state='normal')
        self.logger.info("IP监控已停止")
    
    def monitor_ip_changes(self):
        """监控IP变化"""
        while self._monitoring and not self._exit_event.is_set():
            try:
                # 获取当前IP
                current_local = get_local_ip()
                current_ipv4 = get_ipv4()
                current_ipv6 = get_ipv6()
                
                # 检查是否有变化
                changes = []
                if current_local != self._last_ips["local"]:
                    changes.append(f"本地IP: {self._last_ips['local']} -> {current_local}")
                if current_ipv4 != self._last_ips["ipv4"]:
                    changes.append(f"IPv4: {self._last_ips['ipv4']} -> {current_ipv4}")
                if current_ipv6 != self._last_ips["ipv6"]:
                    changes.append(f"IPv6: {self._last_ips['ipv6']} -> {current_ipv6}")
                
                # 如果有变化，执行更新
                if changes:
                    self.logger.info("检测到IP变化:")
                    for change in changes:
                        self.logger.info(change)
                    self.root.after(0, self.update_now)
                
                # 更新最后的IP记录
                self._last_ips = {
                    "local": current_local,
                    "ipv4": current_ipv4,
                    "ipv6": current_ipv6
                }
                
                # 等待指定时间
                interval_minutes = int(self._monitor_interval.get())
                for _ in range(interval_minutes * 60):  # 转换为秒
                    if not self._monitoring or self._exit_event.is_set():
                        break
                    time.sleep(1)
                    
            except Exception as e:
                self.logger.error(f"监控过程出错: {e}")
                time.sleep(60)  # 出错后等待1分钟再继续
    
    def check_initial_ip_changes(self):
        """启动时检查IP是否有变化"""
        try:
            # 获取当前IP信息
            current_ips = {
                "local": get_local_ip(),
                "ipv4": get_ipv4(),
                "ipv6": get_ipv6()
            }
            
            # 读取保存的IP信息
            if os.path.exists('README.md'):
                with open('README.md', 'r', encoding='utf-8') as f:
                    content = f.read()
                    
                # 提取保存的IP信息
                saved_ips = {}
                local_match = re.search(r'本地IP地址 \| `(.*?)`', content)
                ipv4_match = re.search(r'公网IPv4地址 \| `(.*?)`', content)
                ipv6_match = re.search(r'公网IPv6地址 \| `(.*?)`', content)
                
                saved_ips = {
                    "local": local_match.group(1) if local_match else "无",
                    "ipv4": ipv4_match.group(1) if ipv4_match else "无",
                    "ipv6": ipv6_match.group(1) if ipv6_match else "无"
                }
                
                # 检查是否有变化
                changes = []
                if current_ips["local"] != saved_ips["local"]:
                    changes.append(f"本地IP: {saved_ips['local']} -> {current_ips['local']}")
                if current_ips["ipv4"] != saved_ips["ipv4"]:
                    changes.append(f"IPv4: {saved_ips['ipv4']} -> {current_ips['ipv4']}")
                if current_ips["ipv6"] != saved_ips["ipv6"]:
                    changes.append(f"IPv6: {saved_ips['ipv6']} -> {current_ips['ipv6']}")
                
                if changes:
                    # 有变化，需要更新
                    self.logger.info("启动时检测到IP变化:")
                    for change in changes:
                        self.logger.info(change)
                    self.update_now()
                else:
                    # 无变化，不需要更新
                    self.logger.info("启动时检查: IP未发生变化，无需更新")
                    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                    self.status_var.set("IP未变化，无需更新")
                    self.update_time_var.set(current_time)
            else:
                # 如果文件不存在，执行首次更新
                self.logger.info("首次运行，创建IP信息文件")
                self.update_now()
                
        except Exception as e:
            self.logger.error(f"启动检查IP变化失败: {e}")
            # 如果检查失败，为安全起见执行更新
            self.update_now()

def get_ipv4():
    try:
        response = requests.get('https://api.ipify.org?format=json')
        if response.status_code == 200:
            return response.json()['ip']
    except Exception as e:
        print(f"获取IPv4地址时出错: {e}")
    return "无法获取IPv4地址"

def get_ipv6():
    try:
        response = requests.get('https://v6.ident.me', timeout=5)
        if response.status_code == 200:
            return response.text.strip()
    except Exception:
        try:
            response = requests.get('https://api6.ipify.org?format=json', timeout=5)
            if response.status_code == 200:
                return response.json()['ip']
        except Exception as e:
            print(f"获取IPv6地址时出错: {e}")
    return "无法获取IPv6地址"

def get_local_ip():
    try:
        hostname = socket.gethostname()
        local_ip = socket.gethostbyname(hostname)
        return local_ip
    except Exception as e:
        print(f"获取本地IP地址时出错: {e}")
    return "无法获取本地IP地址"

def generate_markdown():
    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    local_ip = get_local_ip()
    ipv4 = get_ipv4()
    ipv6 = get_ipv6()
    
    markdown_content = f"""# IP 地址信息

> 更新时间: {current_time}

## 网络地址详情

| 地址类型 | IP地址 |
|---------|---------|
| 本地IP地址 | `{local_ip}` |
| 公网IPv4地址 | `{ipv4}` |
| 公网IPv6地址 | `{ipv6}` |

---
*此信息由系统自动生成*
"""
    return markdown_content

def update_markdown_file(markdown_content, file_path='README.md'):
    try:
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(markdown_content)
        print(f"Markdown文件已更新: {file_path}")
    except Exception as e:
        print(f"写入Markdown文件错误: {e}")

def git_commit_and_push():
    try:
        # 获取当前时间作为提交信息
        commit_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        commit_message = f"Update IP info: {commit_time}"
        
        # Git 添加更改
        subprocess.run(['git', 'add', 'README.md'], check=True)
        
        # Git 提交
        subprocess.run(['git', 'commit', '-m', commit_message], check=True)
        
        # Git 推送
        subprocess.run(['git', 'push'], check=True)
        
        print("Git提交和推送成功")
    except subprocess.CalledProcessError as e:
        print(f"Git操作失败: {e}")
    except Exception as e:
        print(f"发生错误: {e}")

def main():
    root = tk.Tk()
    app = UpdateSchedulerGUI(root)
    root.mainloop()

if __name__ == "__main__":
    main() 